﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MagicArenaFramework.GameObject.Components;
using BEPUphysics.Entities;
using BEPUphysics.Entities.Prefabs;
using MagicArenaFramework.Bepu;
using Microsoft.Xna.Framework.Input;
using BEPUphysics.CollisionRuleManagement;
using MagicArenaXNA.ControllerInput.Bepu;
using BEPUphysics.Collidables.MobileCollidables;

namespace MagicArenaXNA.GameObject
{
    public class Targetter : GoComposite
    {
        public static CollisionGroup TargetterGroup = new CollisionGroup();
        public static CollisionGroup Targettable = new CollisionGroup();

        Entity TargetBubble;
        // TODO switch to a pretty model
        Entity TargetReticle;
        List<Entity> TargetList = new List<Entity>(10);
        int TargetIndex = 0;

        public Targetter(Entity self, float targetRadius)
        {
            Self = self;
            CurTargetEntity = self;

            addTargetBubble(self, targetRadius);
            addReticle();

            //add delegates
            this.UpdateDel = MyUpdate;
        }

        public Entity CurTargetEntity { get; private set; }
        public GoComponent CurTargetComp { get; private set; }
        public Entity Self { get; private set; }
        public bool CanAttack
        {
            get
            {
                return true;
            }
        }
        public bool CanHeal
        {
            get
            {
                return (Self.Equals(CurTargetEntity));
            }
        }

        #region AddComponents
        void addReticle(){
            TargetReticle = new Sphere(Self.Position, 1);
            TargetReticle.CollisionInformation.CollisionRules.Personal = BEPUphysics.CollisionRuleManagement.CollisionRule.NoBroadPhase;
            Self.Space.Add(TargetReticle);
        }
        void addTargetBubble(Entity self, float targetRadius)
        {
            TargetBubble = new Sphere(self.Position, 40);
            CustomTag tag = new CustomTag();
            tag.IsBepuDisplayable = false;
            TargetBubble.Tag = tag;
            tag.Component = this;
            tag.TagProp.Add("Name", "TargetBubble");
            addColliders(TargetBubble);
            //Make it so target bubble doesn't collide with self
            TargetBubble.CollisionInformation.CollisionRules.Personal = CollisionRule.NoSolver;
            self.Space.Add(TargetBubble);
        }
        #endregion

        #region Delegates
        KeyboardState prevKeyState = Keyboard.GetState();
        void MyUpdate(float dt)
        {
            KeyboardState keyState = Keyboard.GetState();
            
            // Check if tab was pressed to change targets
            if (keyState.IsKeyDown(Keys.Tab) && prevKeyState.IsKeyUp(Keys.Tab))
            {
                if ((TargetList.Count > 0))
                {
                    // Increment target index while keeping in bounds
                    TargetIndex = ++TargetIndex>=TargetList.Count?0:TargetIndex;
                    CurTargetEntity = TargetList[TargetIndex];
                    CustomTag tag = CurTargetEntity.Tag as CustomTag;
                    if (tag != null)
                        CurTargetComp = tag.Component;
                    else
                        CurTargetComp = null;
                }
            }
            //Check if target is still in range, if not un-target
            if (!TargetList.Contains(CurTargetEntity)) CurTargetEntity = Self;
            prevKeyState = keyState;

            //Update the position of the target bubble
            TargetBubble.Position = Self.Position;

            //TODO Remove this update after getting a pretty model for the reticle
            TargetReticle.Position = CurTargetEntity.Position;
        }
        #endregion

        #region Collision Method
        private void addColliders(Entity range)
        {
            range.CollisionInformation.Events.ContactCreated += new BEPUphysics.Collidables.Events.ContactCreatedEventHandler<BEPUphysics.Collidables.MobileCollidables.EntityCollidable>(Events_ContactCreated);
            range.CollisionInformation.Events.CollisionEnded += new BEPUphysics.Collidables.Events.CollisionEndedEventHandler<BEPUphysics.Collidables.MobileCollidables.EntityCollidable>(Events_CollisionEnded);
        }
        void Events_ContactCreated(BEPUphysics.Collidables.MobileCollidables.EntityCollidable sender, BEPUphysics.Collidables.Collidable other, BEPUphysics.NarrowPhaseSystems.Pairs.CollidablePairHandler pair, BEPUphysics.CollisionTests.ContactData contact)
        {
            if (other is EntityCollidable)
            {
                Entity entity = (other as EntityCollidable).Entity;
                CustomTag tag = entity.Tag as CustomTag;
                if (tag != null)
                {
                    if (tag.IsTargettable)
                    {
                        if(!TargetList.Contains(entity)) TargetList.Add(entity);
                    }
                }
            }
        }
        void Events_CollisionEnded(BEPUphysics.Collidables.MobileCollidables.EntityCollidable sender, BEPUphysics.Collidables.Collidable other, BEPUphysics.NarrowPhaseSystems.Pairs.CollidablePairHandler pair)
        {
            if (other is EntityCollidable)
            {
                Entity entity = (other as EntityCollidable).Entity;
                CustomTag tag = entity.Tag as CustomTag;
                if (tag != null)
                {
                    if (tag.IsTargettable)
                    {
                        bool rtn = TargetList.Remove(entity);
                        
                    }
                }
            }
        }
        #endregion
    }
}
